package com.yy.yunpan.share.service.impl;

import com.yy.yunpan.common.constant.Constants;
import com.yy.yunpan.common.exception.BusinessException;
import com.yy.yunpan.common.result.ResultCode;
import com.yy.yunpan.file.entity.File;
import com.yy.yunpan.file.repository.FileRepository;
import com.yy.yunpan.share.entity.Share;
import com.yy.yunpan.share.repository.ShareRepository;
import com.yy.yunpan.share.service.ShareService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Random;

/**
 * 分享服务实现类
 *
 * @author YY
 * @since 2025-10-01
 */
@Service
@Transactional
public class ShareServiceImpl implements ShareService {

    private static final Logger logger = LoggerFactory.getLogger(ShareServiceImpl.class);

    @Autowired
    private ShareRepository shareRepository;

    @Autowired
    private FileRepository fileRepository;

    @Override
    public Share createShare(Long userId, Long fileId, String shareName, Integer permissions, String password, LocalDateTime expireTime) {
        // 参数校验
        if (userId == null || fileId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        // 检查文件是否存在且属于当前用户
        File file = fileRepository.findByIdAndUserId(fileId, userId)
                .orElseThrow(() -> new BusinessException(ResultCode.ERROR.getCode(), "文件不存在或无权限"));

        // 检查文件状态
        if (!Integer.valueOf(Constants.FileStatus.NORMAL).equals(file.getStatus())) {
            throw new BusinessException(ResultCode.ERROR.getCode(), "文件不可分享");
        }

        try {
            // 生成唯一分享码
            String shareCode = generateUniqueShareCode();

            // 创建分享记录
            Share share = new Share();
            share.setUserId(userId);
            share.setFileId(fileId);
            share.setShareCode(shareCode);
            share.setShareName(StringUtils.isNotBlank(shareName) ? shareName : file.getFileName());
            share.setPermissions(permissions != null ? permissions : 2); // 默认下载权限
            share.setPassword(password);
            share.setExpireTime(expireTime);
            share.setCreateTime(LocalDateTime.now());
            share.setUpdateTime(LocalDateTime.now());

            share = shareRepository.save(share);

            logger.info("创建分享成功：用户ID={}, 文件ID={}, 分享码={}", userId, fileId, shareCode);
            return share;
        } catch (Exception e) {
            logger.error("创建分享失败：用户ID={}, 文件ID={}", userId, fileId, e);
            throw new BusinessException(ResultCode.ERROR.getCode(), "创建分享失败");
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> getShareByCode(String shareCode) {
        if (StringUtils.isBlank(shareCode)) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        // 查找分享记录
        Share share = shareRepository.findByShareCode(shareCode)
                .orElseThrow(() -> new BusinessException(ResultCode.ERROR.getCode(), "分享不存在"));

        // 检查分享状态
        if (share.getStatus() != 1) {
            throw new BusinessException(ResultCode.ERROR.getCode(), "分享已失效");
        }

        // 检查是否过期
        if (share.getExpireTime() != null && share.getExpireTime().isBefore(LocalDateTime.now())) {
            // 更新分享状态为失效
            share.setStatus(0);
            share.setUpdateTime(LocalDateTime.now());
            shareRepository.save(share);
            throw new BusinessException(ResultCode.ERROR.getCode(), "分享已过期");
        }

        // 获取文件信息
        File file = fileRepository.findById(share.getFileId())
                .orElseThrow(() -> new BusinessException(ResultCode.ERROR.getCode(), "文件不存在"));

        // 检查文件状态
        if (!Integer.valueOf(Constants.FileStatus.NORMAL).equals(file.getStatus())) {
            throw new BusinessException(ResultCode.ERROR.getCode(), "文件不可访问");
        }

        Map<String, Object> result = new HashMap<>();
        result.put("shareId", share.getId());
        result.put("shareName", share.getShareName());
        result.put("permissions", share.getPermissions());
        result.put("needPassword", StringUtils.isNotBlank(share.getPassword()));
        result.put("expireTime", share.getExpireTime());
        result.put("visitCount", share.getVisitCount());
        result.put("downloadCount", share.getDownloadCount());

        // 文件信息
        Map<String, Object> fileInfo = new HashMap<>();
        fileInfo.put("id", file.getId());
        fileInfo.put("fileName", file.getFileName());
        fileInfo.put("fileSize", file.getFileSize());
        fileInfo.put("fileType", file.getFileType());
        fileInfo.put("isFolder", file.getIsFolder());
        fileInfo.put("createTime", file.getCreateTime());
        result.put("file", fileInfo);

        return result;
    }

    @Override
    public Map<String, Object> verifySharePassword(String shareCode, String password) {
        if (StringUtils.isBlank(shareCode)) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        // 查找分享记录
        Share share = shareRepository.findByShareCode(shareCode)
                .orElseThrow(() -> new BusinessException(ResultCode.ERROR.getCode(), "分享不存在"));

        // 检查分享状态
        if (share.getStatus() != 1) {
            throw new BusinessException(ResultCode.ERROR.getCode(), "分享已失效");
        }

        // 检查是否需要密码
        if (StringUtils.isBlank(share.getPassword())) {
            throw new BusinessException(ResultCode.ERROR.getCode(), "此分享无需密码");
        }

        // 验证密码
        if (!share.getPassword().equals(password)) {
            throw new BusinessException(ResultCode.ERROR.getCode(), "分享密码错误");
        }

        // 增加访问次数
        incrementVisitCount(shareCode);

        // 获取文件信息
        File file = fileRepository.findById(share.getFileId())
                .orElseThrow(() -> new BusinessException(ResultCode.ERROR.getCode(), "文件不存在"));

        Map<String, Object> result = new HashMap<>();
        result.put("verified", true);

        // 文件信息
        Map<String, Object> fileInfo = new HashMap<>();
        fileInfo.put("id", file.getId());
        fileInfo.put("fileName", file.getFileName());
        fileInfo.put("fileSize", file.getFileSize());
        fileInfo.put("fileType", file.getFileType());
        fileInfo.put("isFolder", file.getIsFolder());
        result.put("file", fileInfo);

        return result;
    }

    @Override
    @Transactional(readOnly = true)
    public Page<Share> getUserShareList(Long userId, Integer page, Integer size, String orderBy, String orderType) {
        if (userId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        if (page == null || page < 1) page = 1;
        if (size == null || size < 1) size = 20;
        if (StringUtils.isBlank(orderBy)) orderBy = "createTime";
        if (StringUtils.isBlank(orderType)) orderType = "desc";

        Sort.Direction direction = "asc".equalsIgnoreCase(orderType) ? Sort.Direction.ASC : Sort.Direction.DESC;
        Sort sort = Sort.by(direction, orderBy);
        Pageable pageable = PageRequest.of(page - 1, size, sort);

        try {
            Page<Share> sharePage = shareRepository.findByUserId(userId, pageable);
            logger.info("获取用户分享列表成功：用户ID={}, 总数={}", userId, sharePage.getTotalElements());
            return sharePage;
        } catch (Exception e) {
            logger.error("获取用户分享列表失败：用户ID={}", userId, e);
            throw new BusinessException(ResultCode.ERROR.getCode(), "获取分享列表失败");
        }
    }

    @Override
    public void cancelShare(Long userId, Long shareId) {
        if (userId == null || shareId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        // 查找分享记录
        Share share = shareRepository.findById(shareId)
                .orElseThrow(() -> new BusinessException(ResultCode.ERROR.getCode(), "分享不存在"));

        // 检查权限
        if (!share.getUserId().equals(userId)) {
            throw new BusinessException(ResultCode.ERROR.getCode(), "无权限操作");
        }

        try {
            // 设置为失效状态
            share.setStatus(0);
            share.setUpdateTime(LocalDateTime.now());
            shareRepository.save(share);

            logger.info("取消分享成功：用户ID={}, 分享ID={}", userId, shareId);
        } catch (Exception e) {
            logger.error("取消分享失败：用户ID={}, 分享ID={}", userId, shareId, e);
            throw new BusinessException(ResultCode.ERROR.getCode(), "取消分享失败");
        }
    }

    @Override
    public Share updateShare(Long userId, Long shareId, String shareName, Integer permissions, String password, LocalDateTime expireTime) {
        if (userId == null || shareId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        // 查找分享记录
        Share share = shareRepository.findById(shareId)
                .orElseThrow(() -> new BusinessException(ResultCode.ERROR.getCode(), "分享不存在"));

        // 检查权限
        if (!share.getUserId().equals(userId)) {
            throw new BusinessException(ResultCode.ERROR.getCode(), "无权限操作");
        }

        try {
            // 更新分享信息
            if (StringUtils.isNotBlank(shareName)) {
                share.setShareName(shareName);
            }
            if (permissions != null) {
                share.setPermissions(permissions);
            }
            share.setPassword(password); // 允许设置为空来取消密码
            share.setExpireTime(expireTime); // 允许设置为空来取消过期时间
            share.setUpdateTime(LocalDateTime.now());

            share = shareRepository.save(share);

            logger.info("更新分享成功：用户ID={}, 分享ID={}", userId, shareId);
            return share;
        } catch (Exception e) {
            logger.error("更新分享失败：用户ID={}, 分享ID={}", userId, shareId, e);
            throw new BusinessException(ResultCode.ERROR.getCode(), "更新分享失败");
        }
    }

    @Override
    public void incrementVisitCount(String shareCode) {
        if (StringUtils.isBlank(shareCode)) {
            return;
        }

        try {
            shareRepository.incrementVisitCount(shareCode, LocalDateTime.now());
        } catch (Exception e) {
            logger.warn("更新访问次数失败：分享码={}", shareCode, e);
        }
    }

    @Override
    public void incrementDownloadCount(String shareCode) {
        if (StringUtils.isBlank(shareCode)) {
            return;
        }

        try {
            shareRepository.incrementDownloadCount(shareCode, LocalDateTime.now());
        } catch (Exception e) {
            logger.warn("更新下载次数失败：分享码={}", shareCode, e);
        }
    }

    @Override
    public void updateExpiredShares() {
        try {
            shareRepository.updateExpiredSharesStatus(LocalDateTime.now(), LocalDateTime.now());
            logger.info("更新过期分享状态成功");
        } catch (Exception e) {
            logger.error("更新过期分享状态失败", e);
        }
    }

    /**
     * 生成唯一分享码
     */
    private String generateUniqueShareCode() {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        String shareCode;
        int attempts = 0;
        int maxAttempts = 10;

        do {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 12; i++) {
                sb.append(chars.charAt(random.nextInt(chars.length())));
            }
            shareCode = sb.toString();
            attempts++;
        } while (shareRepository.existsByShareCode(shareCode) && attempts < maxAttempts);

        if (attempts >= maxAttempts) {
            throw new BusinessException(ResultCode.ERROR.getCode(), "生成分享码失败，请重试");
        }

        return shareCode;
    }
}